package com.douqu.game.core.factory;

import com.douqu.game.core.database.model.GMLogModel;
import com.douqu.game.core.database.model.GMModel;
import com.douqu.game.core.database.model.PlayerModel;
import com.douqu.game.core.database.model.ServerModel;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.util.CoreUtils;

import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Bean
 * @Description:
 * @Date: 2018-03-24 15:33
 */
public class DatabaseFactory {

    public DatabaseConfig databaseConfig;

    public DatabaseFactory(DatabaseConfig databaseConfig)
    {
        this.databaseConfig = databaseConfig;
    }

    private Connection getConnection()
    {
        try {
            // 加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            return DriverManager.getConnection(databaseConfig.getUrl(), databaseConfig.getUser(), databaseConfig.getPwd());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public List<GMModel> getGMList()
    {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<GMModel> gmModelList = new ArrayList<>();
        try {
            connection = getConnection();
            ps = connection.prepareStatement("select * from gm");
            rs = ps.executeQuery();
            GMModel gmModel = null;
            while(rs.next())
            {
                gmModel = new GMModel();
                gmModel.setId(rs.getInt("id"));
                gmModel.setUsername(rs.getString("username"));
                gmModel.setPassword(rs.getString("password"));
                gmModel.setType(rs.getInt("type"));
                gmModel.setCreateTime(rs.getTimestamp("createTime"));
                gmModel.setDel(rs.getBoolean("isDel"));
                gmModelList.add(gmModel);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs != null)
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return gmModelList;
    }

    public List<GMLogModel> getGMLogList()
    {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<GMLogModel> gmLogModelList = new ArrayList<>();
        try {
            connection = getConnection();
            ps = connection.prepareStatement("select * from gm_log");
            rs = ps.executeQuery();
            GMLogModel gmLogModel = null;
            while(rs.next())
            {
                gmLogModel = new GMLogModel();
                gmLogModel.setOptionPerson(rs.getString("optionPerson"));
                gmLogModel.setContent(rs.getString("content"));
                gmLogModel.setType(rs.getInt("type"));
                gmLogModel.setValue(rs.getString("value"));
                gmLogModel.setPlayerIndex(rs.getString("playerIndex"));
                gmLogModel.setCreateTime(rs.getTimestamp("createTime"));
                gmLogModelList.add(gmLogModel);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs != null)
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return gmLogModelList;
    }

    public int getRobotCount()
    {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            connection = getConnection();
            ps = connection.prepareStatement("select count(1) from player where uid =0");
            rs = ps.executeQuery();
            if(rs.next())
            {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs != null)
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return 0;
    }
    public int getRealPlayerCount()
    {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            connection = getConnection();
            ps = connection.prepareStatement("select count(1) from player where uid != 0");
            rs = ps.executeQuery();
            if(rs.next())
            {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs != null)
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return 0;
    }

    public Player loadPlayer(String account)
    {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            connection = getConnection();
            ps = connection.prepareStatement("select * from player where uid = (select id from user where account=? or deviceId=?)");
            ps.setString(1, account);
            ps.setString(2, account);
            rs = ps.executeQuery();
            if(rs.next())
            {
                PlayerModel playerModel = new PlayerModel();
                playerModel.setId(rs.getInt("id"));
                playerModel.setObjectIndex(rs.getString("objectIndex"));
                playerModel.setUid(rs.getInt("uid"));
                playerModel.setName(rs.getString("name"));
                playerModel.setAvatar(rs.getString("avatar"));
                playerModel.setCamp(rs.getInt("camp"));
                playerModel.setLevel(rs.getInt("level"));
                playerModel.setExp(rs.getInt("exp"));
                playerModel.setVipLevel(rs.getInt("vipLevel"));
                playerModel.setVipExp(rs.getInt("vipExp"));
                playerModel.setMaster(rs.getInt("master"));
                playerModel.setFc(rs.getInt("fc"));
                playerModel.setMoney(rs.getInt("money"));
                playerModel.setBagInfo(rs.getBytes("bagInfo"));
                playerModel.setSettingInfo(rs.getBytes("settingInfo"));
                playerModel.setChallengeInfo(rs.getBytes("challengeInfo"));
                playerModel.setTaskInfo(rs.getBytes("taskInfo"));
                playerModel.setBoonInfo(rs.getBytes("boonInfo"));
                playerModel.setMailInfo(rs.getBytes("mailInfo"));
                playerModel.setMajorInfo(rs.getBytes("majorInfo"));
                playerModel.setIsDel(rs.getBoolean("isDel"));
                playerModel.setCreateTime(rs.getTimestamp("createTime"));
                playerModel.setLastLoginTime(rs.getTimestamp("lastLoginTime"));
                playerModel.setLastLogoutTime(rs.getTimestamp("lastLogoutTime"));

                return new Player(playerModel);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs != null)
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return null;
    }






    public List<Player> getAllPlayer()
    {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<Player> playerList = new ArrayList<>();
        try {
            connection = getConnection();
            ps = connection.prepareStatement("select * from player");
            rs = ps.executeQuery();
            PlayerModel playerModel = null;
            while(rs.next())
            {
                playerModel = new PlayerModel();
                playerModel.setId(rs.getInt("id"));
                playerModel.setObjectIndex(rs.getString("objectIndex"));
                playerModel.setUid(rs.getInt("uid"));
                playerModel.setName(rs.getString("name"));
                playerModel.setAvatar(rs.getString("avatar"));
                playerModel.setCamp(rs.getInt("camp"));
                playerModel.setLevel(rs.getInt("level"));
                playerModel.setExp(rs.getInt("exp"));
                playerModel.setVipLevel(rs.getInt("vipLevel"));
                playerModel.setVipExp(rs.getInt("vipExp"));
                playerModel.setMaster(rs.getInt("master"));
                playerModel.setFc(rs.getInt("fc"));
                playerModel.setMoney(rs.getInt("money"));
                playerModel.setBagInfo(rs.getBytes("bagInfo"));
                playerModel.setSettingInfo(rs.getBytes("settingInfo"));
                playerModel.setChallengeInfo(rs.getBytes("challengeInfo"));
                playerModel.setTaskInfo(rs.getBytes("taskInfo"));
                playerModel.setBoonInfo(rs.getBytes("boonInfo"));
                playerModel.setMailInfo(rs.getBytes("mailInfo"));
                playerModel.setMajorInfo(rs.getBytes("majorInfo"));
                playerModel.setIsDel(rs.getBoolean("isDel"));
                playerModel.setCreateTime(rs.getTimestamp("createTime"));
                playerModel.setLastLoginTime(rs.getTimestamp("lastLoginTime"));
                playerModel.setLastLogoutTime(rs.getTimestamp("lastLogoutTime"));

                playerList.add(new Player(playerModel));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs != null)
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return playerList;
    }

    public ServerModel getServerModel(){
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        ServerModel serverModel = null;
        try{
            connection = getConnection();
            ps = connection.prepareStatement("SELECT * FROM server LIMIT 1");
            rs = ps.executeQuery();
            while(rs.next())
            {
                serverModel = new ServerModel();
                serverModel.setName(rs.getString("name"));
                serverModel.setPlayerIndex(rs.getInt("playerIndex"));
                serverModel.setGoodsIndex(rs.getInt("goodsIndex"));
                serverModel.setAuthServerHost(rs.getString("authServerHost"));
                serverModel.setFreeCount(rs.getInt("freeCount"));
                serverModel.setCrowdCount(rs.getInt("crowdCount"));
                serverModel.setWorldInfo(rs.getBytes("worldInfo"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs != null)
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return serverModel;
    }

    public List<Map<String, Object>> query(String sql)
    {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<Map<String, Object>> list = new ArrayList<>();
        try {
            connection = getConnection();
            ps = connection.prepareStatement(sql);
            rs = ps.executeQuery();
            Map<String, Object> result = null;
            ResultSetMetaData metaData = rs.getMetaData();
            int count = metaData.getColumnCount();
            while(rs.next())
            {
                result = new HashMap<>();
                for(int i = 1; i <= count; i++)
                {
                    result.put(metaData.getColumnName(i), rs.getObject(i));
                }
                list.add(result);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs != null)
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return list;
    }


    public int execute(String sql, Object... params)
    {
        Connection connection = null;
        PreparedStatement ps = null;
        try {
            connection = getConnection();
            ps = connection.prepareStatement(sql);
            int i = 0;
            for(Object obj : params)
            {
                ps.setObject(++i, obj);
            }
            ps.execute();
            return ps.getUpdateCount();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
        return 0;
    }




    public boolean isTableExist(String tableName)
    {
        Connection connection = getConnection();
        ResultSet rsTables = null;
        try {
            rsTables = connection.getMetaData().getTables(null, null, tableName, null);
            return rsTables.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                rsTables.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    public boolean isDBExist()
    {
        Connection connection = null;
        PreparedStatement ps = null;
        try {
            connection = DriverManager.getConnection(databaseConfig.getUrl(), databaseConfig.getUser(), databaseConfig.getPwd());
            return connection != null;
        } catch (Exception e) {
            return false;
        }finally {

            if(ps != null)
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            if(connection != null)
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
    }


    public static InputStream getFileInputStream(String filePath) throws Exception
    {
        File file = null;
        if(filePath.startsWith("C:") || filePath.startsWith("D:")
                || filePath.startsWith("E:") || filePath.startsWith("F:") || filePath.startsWith("G:"))
            file = new File(filePath);
        else
            file = new File(CoreUtils.getBasePath() + filePath);

        if(!file.exists())
            file = new File(CoreUtils.getRootPath() + filePath);

        InputStream input = null;
        if(file.exists())
        {
            input = new BufferedInputStream(new FileInputStream(file));
        }
        else
        {
            input = LoadFactory.class.getClassLoader().getResourceAsStream(filePath);
        }
        return input;
    }
}
